/*
 *	OpenSource code or fragments by agile webentwicklung, Marcus Fuhrmeister
 *
 *	Redistribution and use in source and binary forms, with or without
 *	modification, are permitted provided that the following conditions
 *	are met:
 *  
 *		* Redistribution of source code must retain the above OpenSource comment,
 *		this list of conditions and the following disclaimer.
 * 
 *		* Redistribution in binary form must reproduce the above OpenSource comment,
 *		this list of conditions and the following disclaimer in the
 *		documentation and/or other materials provided with the distribution.
 * 
 *	Neither the name of 'avocaod systems, Marcus Fuhrmeister' or the
 *	names of contributors may be used to endorse or promote products derived
 *	from this software without specific prior written permission.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 */
package de.fuhrmeister.browserchooser.controller;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;

import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import de.fuhrmeister.browserchooser.view.BrowserView;
import de.fuhrmeister.browserchooser.view.DummyView;
import de.fuhrmeister.browserchooser.view.SettingsView;
import de.fuhrmeister.util.ConfigManager;
import de.fuhrmeister.util.ImageManager;
import de.fuhrmeister.util.Tools;

/**
 * Controller class handling the view.
 * 
 * @date 20.11.2008
 * @author Marcus Fuhrmeister
 */
public class SettingsController extends WindowAdapter implements WindowFocusListener, ChangeListener, ActionListener {
	private static final String TITLE = "BrowserChooser";
	private static SettingsController self;
	private SettingsView settings;
	private boolean isInsertingTab = false;

	/**
	 * Singleton pattern.
	 * 
	 * @return this
	 */
	public static synchronized SettingsController getInstance() {
		if (self == null) {
			SettingsController.self = new SettingsController();
			return SettingsController.self;
		}
		return SettingsController.self;
	}

	/**
	 * Inits the view.
	 */
	public void init() {
		settings = new SettingsView(Controller.getInstance().getFrame(Controller.APP_WINDOW_MAIN), TITLE+" - "+Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_SETTINGS), ImageManager.getInstance().getImage(ImageManager.APPLICATION));
		settings.setSize(Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_SIZE_WIDTH)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_SIZE_HEIGHT)));
		settings.setLocation(Controller.SYSTEM_SCREEN_WIDTH / 2 - settings.getWidth() / 2, Controller.SYSTEM_SCREEN_HEIGHT / 2 - settings.getHeight() / 2);

		settings.initItems();
		settings.setButtonPanelSize(Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTONPANEL_SIZE_WIDTH)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTONPANEL_SIZE_HEIGHT)));
		settings.setButtonBounds(SettingsView.ITEM_BUTTON_SAVE, Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_SAVE_COORDINATE_X)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_SAVE_COORDINATE_Y)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_SAVE_SIZE_WIDTH)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_SAVE_SIZE_HEIGHT)));
		settings.setButtonBounds(SettingsView.ITEM_BUTTON_ABORT, Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_ABORT_COORDINATE_X)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_ABORT_COORDINATE_Y)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_ABORT_SIZE_WIDTH)), Integer.parseInt(Tools.configMng.getConfiguration(ConfigManager.SETTINGS_BUTTON_ABORT_SIZE_HEIGHT)));
		settings.setButtonText(SettingsView.ITEM_BUTTON_SAVE, Tools.configMng.getStringFor(ConfigManager.STRING_BUTTON_SAVE));
		settings.setButtonText(SettingsView.ITEM_BUTTON_ABORT, Tools.configMng.getStringFor(ConfigManager.STRING_BUTTON_ABORT));
		settings.setActionCommand(SettingsView.ITEM_BUTTON_SAVE, Tools.configMng.getStringFor(ConfigManager.STRING_BUTTON_SAVE));
		settings.setActionCommand(SettingsView.ITEM_BUTTON_ABORT, Tools.configMng.getStringFor(ConfigManager.STRING_BUTTON_ABORT));
		settings.addView(Tools.configMng.getStringFor(ConfigManager.STRING_LABEL_OPTIONS), OptionsController.getInstance().getView());

		final BrowserView[] bvs = BrowserController.getInstance().getViews();
		if (bvs != null) {
			for (final BrowserView bv : bvs) {
				if (bv != null) {
					settings.addView(bv.getBrowserName(), bv);
				}
			}
		}

		settings.addView(Tools.configMng.getStringFor(ConfigManager.STRING_TAB_LABEL_NEW), new DummyView());

		setListeners();
	}

	/**
	 * Calls to register the listeners.
	 */
	private void setListeners() {
		settings.registerListener(this);
	}

	/**
	 * Calls to inits the view and shows it.
	 */
	public void show() {
		if (settings == null) {
			this.init();
		}
		settings.setVisible(true);
		settings.toFront();
		settings.requestFocus();
	}

	/**
	 * Calls to inits the view and shows it.
	 * 
	 * @param id the browser id
	 */
	public void show(final int id) {
		if (settings == null) {
			this.init();
		}settings.setVisible(true);
		settings.toFront();
		settings.focusView(id);
	}

	/**
	 * Calls to init the view, calls to create a new view and calls to show it in this view.
	 * 
	 * @param name the browser name
	 * @param absolutePath the absolute path of the browser executable
	 */
	public void show(final String name, final String absolutePath) {
		if (settings == null) {
			this.init();
		}
		this.createBrowserView(name, absolutePath);
		// -2, because of zero indexed tab count and we do not want the last DummyView to be selected
		this.show(settings.getViewCount()-2);
	}

	/**
	 * Disposes the view.
	 */
	private void invalidate() {
		settings.dispose();
		settings = null;
	}

	/**
	 * Calls to invalidate the view if the parameter is true.
	 * 
	 * @param delete true if the view shall be invalidated
	 */
	public void close(final boolean delete) {
		settings.toBack();
		settings.setVisible(false);
		if (delete) {
			this.invalidate();
			BrowserController.getInstance().invalidate();
		}
	}

	/**
	 * Returns the view.
	 * 
	 * @return this component
	 */
	public Component getWindow() {
		return settings;
	}
	
	/**
	 * Calls to create and insert a new browser view with the given name and executable path.
	 * 
	 * @param name the browser name
	 * @param absolutePath the absolute path of the browser executable
	 */
	private void createBrowserView(final String name, final String absolutePath) {
		this.isInsertingTab = true;
		final BrowserView bv = BrowserController.getInstance().createView(name, absolutePath);
		settings.insertView(bv.getBrowserName(), bv, settings.getViewCount() - 1);
		this.isInsertingTab = false;
	}

	/**
	 * Calls to set the browser view with the given id enabled.
	 * 
	 * @param browserID the browser id
	 * @param enabled true if the browser view shall be enabled
	 */
	public void setViewEnabled(final int browserID, final boolean enabled) {
		settings.setViewEnabled(browserID, enabled);
		if (!enabled) {
			settings.focusView(0);
		}
	}

	/**
	 * Calls to enable all browser views.
	 */
	public void resetViews() {
		for (int counter = settings.getViewCount() - 2; counter == 1; counter--) {
			settings.setViewEnabled(counter, true);
		}
	}

	/**
	 * The view`s action listener method.
	 * Calls to save or abort the new browser and option settings.
	 * Closes thid view and calls to update the application.
	 */
	public void actionPerformed(final ActionEvent e) {
		if (e.getActionCommand().equalsIgnoreCase(Tools.configMng.getStringFor(ConfigManager.STRING_BUTTON_SAVE))) {
			OptionsController.getInstance().save();
			BrowserController.getInstance().save();
			this.close(true);
			Controller.getInstance().update();
			Controller.getInstance().focus(Controller.APP_WINDOW_MAIN);
		}
		if (e.getActionCommand().equalsIgnoreCase(Tools.configMng.getStringFor(ConfigManager.STRING_BUTTON_ABORT))) {
			this.resetViews();
			OptionsController.getInstance().abort();
			BrowserController.getInstance().abort();
			this.close(true);
			Controller.getInstance().focus(Controller.APP_WINDOW_MAIN);
		}
	}

	/**
	 * The view`s window listener method.
	 * Calls to focus on the main application view.
	 * 
	 * @param event the window event
	 */
	public void windowClosing(final WindowEvent event) {
		this.close(true);
		Controller.getInstance().focus(Controller.APP_WINDOW_MAIN);
	}

	/**
	 * The view`s window focus listener method.
	 * Invoked when the Window is no longer the focused Window, which means that
	 * keyboard events will no longer be delivered to the Window or any of its
	 * subcomponents.
	 */
	public void windowLostFocus(final WindowEvent e) {
		this.show();
	}

	/**
	 * The view`s change listener method.
	 * Evaluates if the last tab was clicked and calls to show this view with a new browser view 
	 */
	public void stateChanged(final ChangeEvent e) {
		if (!this.isInsertingTab) {
		if (e.getSource() instanceof JTabbedPane) {
			if (((JTabbedPane) e.getSource()).getSelectedIndex() == ((JTabbedPane) e.getSource()).getTabCount() - 1) {
				this.show(null, null);
			}
		}
		}
	}
}
